'/
' RabMT (Rabid Multi-Threading) - A multi-threading Library
' Written 2010 by Anton Berlin.
' 
' =========================================================================
' 
'                                Version 1.0
' 
' =========================================================================
' 
' This program is free software; you can redistribute it and/or modify
' it under the terms of the GNU Lesser General Public License as published
' by the Free Software Foundation; either version 3 of the License.
' 
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.
' 
' You should have received a copy of the GNU Lesser General Public License
' along with this program; if not, write to the Free Software
' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'/

superstrict

import BRL.Threads
import BRL.Map
import BRL.Reflection

type RabMT

	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		Private thread container.
	'// -----------------------------------------------------------------------------------------------------------------
	global _threads:TMap = new TMap;
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		Private mutex container.
	'// -----------------------------------------------------------------------------------------------------------------
	global _mutexes:TMap = new TMap;
	global _mutexesConst:TMap = new TMap;
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		Create a new thread and launch it.
	'// 
	'// Parameters:
	'// 		(string) name: What we want to call the new thread. This is used to identify the thread.
	'// 		(object) func: A pointer to the function that should be called when the thread launches.
	'// 		(object) data: The data that we pass to the launch function.
	'// -----------------------------------------------------------------------------------------------------------------
	function launchThread:byte(name:string, func:object(data:object), data:object)
	
		local thread:TThread = createThread(func, data);
		
		if (thread) then
		
			_threads.insert(name, thread);
			return true;
		
		end if
		
		return false;
	
	end function
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		Returns a specific thread.
	'// 
	'// Parameters:
	'// 		(string) name: The name of the thread to retrieve.
	'// -----------------------------------------------------------------------------------------------------------------
	function getThread:TThread(name:string)
	
		return TThread(_threads.valueForKey(name));
	
	end function
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		Create a new mutex.
	'// 
	'// Parameters:
	'// 		(string) name: What we want to call the new mutex. This is used to identify the mutex.
	'// 		(short) constant: The optional constant used to identify the mutex. You can put name to null and use this
	'//      	instead, if you want. It works just as well.
	'// -----------------------------------------------------------------------------------------------------------------
	function newMutex:byte(name:string, constant:short = -1)
	
		local mutex:TMutex = createMutex();
		
		if (constant = -1 and name = null) ..
			return false;
		
		if (mutex) then
		
			if (name) ..
				_mutexes.insert(name, mutex);
			if (constant > -1) ..
				_mutexesConst.insert(string(constant), mutex);
			return true;
		
		end if
		
		return false;
	
	end function
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		Returns a specific mutex, identified either by its constant id or by its name.
	'// 
	'// Parameters:
	'// 		(string) id: The name or constant id of the mutex to retrieve.
	'// -----------------------------------------------------------------------------------------------------------------
	function getMutex:TMutex(id:string)
	
		local numid:string = int(id);
		local mutex:TMutex;
		
		'// Try using the id as a mutex name.
		mutex = TMutex(_mutexes.valueForKey(id));
		if (mutex) ..
			return mutex
		
		'// If no mutex was identified, see if the id is an integer that is 0 or higher, and use it as a constant id to
		'// try to identify the mutex.
		if (numid >= 0) then
		
			mutex = TMutex(_mutexesConst.valueForKey(id));
			return mutex;
		
		end if
	
	end function
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		Halt the execution until a thread finishes.
	'// 
	'// Parameters:
	'// 		(string) name: The name of the thread to wait for.
	'// -----------------------------------------------------------------------------------------------------------------
	function waitThread(name:string)
	
		.waitThread(getThread(name));
	
	end function
	
	'// -----------------------------------------------------------------------------------------------------------------
	'// Description:
	'// 		Prevent this type to be instantiated.
	'// -----------------------------------------------------------------------------------------------------------------
	method new()
	
		local id:string = TTypeId.forObject(self).Name();
		runtimeError("Illegal to create an instance of a namespace class '" + id + "'.");
	
	end method

end type
